﻿
using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using PCR.Base;
using PCR.Logic;

namespace PCR
{    
    //public partial class StandardCurveForm : Form
    public partial class StandardCurveForm : DevComponents.DotNetBar.Office2007Form
    {
        private ListViewColumnSorter lvwColumnSorter;
        
        #region "Main Form Initialize and Close"
        public StandardCurveForm()
        {
            InitializeComponent();
            lvwColumnSorter = new ListViewColumnSorter();
            this.listSampleData.ListViewItemSorter = lvwColumnSorter;
        }

        private void StandardCurveForm_Load(object sender, EventArgs e)
        {
            this.listSamples.ContextMenuStrip = this.cmsSamples;
            this.listSampleData.ContextMenuStrip = this.cmsCurSample;
        }

        private void StandardCurveForm_Shown(object sender, EventArgs e)
        {
            IList<IStdCurve> stdSamples = PCRRoot.Instance.StdCurveManager.List;

            foreach (IStdCurve stdSample in stdSamples)
            {
                AddNewItemFromStdSample(stdSample);
            }

            if (stdSamples.Count > 0)
            {
                this.listSamples.Items[0].Selected = true;
            }

            //this.listSampleData.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);
        }

        private void StandardCurveForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.listSampleData.ItemChecked -= new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked); 
        }

        private void StandardCurveForm_Resize(object sender, EventArgs e)
        {
            ReSetChartSize();
        }
        #endregion

        #region "ListSamples Event"

        private void btnAddSample_Click(object sender, EventArgs e)
        {
            AddSample();
        }

        private void btnDeleteSample_Click(object sender, EventArgs e)
        {
            DeleteSelectedSamples();
        }

        private void btnImport_Click(object sender, EventArgs e)
        {

        }

        private void btnModifySample_Click(object sender, EventArgs e)
        {
            EditSelectedSamples();
        }

        private void listSamples_DoubleClick(object sender, EventArgs e)
        {
            EditSelectedSamples();
        }

        private void listSamples_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.listSamples.SelectedItems.Count == 0)
            {
                this.listSampleData.Items.Clear();
                ClearChartPoints();
                return;
            }

            IStdCurve stdSamples = this.listSamples.SelectedItems[0].Tag as IStdCurve;
            if (stdSamples == null)
                return;

            this.listSampleData.ItemChecked -= new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);
            UpdateStdSamples(stdSamples);
            this.listSampleData.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);

        }

        private void tsmAdd_Click(object sender, EventArgs e)
        {
            AddSample();
        }

        private void tsmModify_Click(object sender, EventArgs e)
        {
            EditSelectedSamples();
        }

        private void tsmDelete_Click(object sender, EventArgs e)
        {
            DeleteSelectedSamples();
        }

        private void tsmSelect_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in this.listSamples.Items)
            {
                item.Selected = true;
            }
        }

        private void tsmSetStd_Click(object sender, EventArgs e)
        {
            if (this.listSamples.SelectedItems.Count <= 0)
            {
                return;
            }

            IStdCurve stdSamples = this.listSamples.SelectedItems[0].Tag as IStdCurve;
            if (IsStandard(stdSamples)) return;

            PCRRoot.Instance.StdCurveManager.Active = stdSamples;

            foreach(ListViewItem item in this.listSamples.Items)
            {
                item.BackColor = Control.DefaultBackColor;
            }

            this.listSamples.SelectedItems[0].BackColor = Color.Red;          
        }

        #endregion

        #region "ListSamples Methods"
        // Judge if is Standard
        private bool IsStandard(IStdCurve curve)
        {
            if (curve == null) return false;
            if (PCRRoot.Instance.StdCurveManager.Active == null) return false;
            return (PCRRoot.Instance.StdCurveManager.Active.ObjectID == curve.ObjectID);            
        }

        // Add a StdSample to ListSamples
        void AddNewItemFromStdSample(IStdCurve stdSample)
        {
            ListViewItem item = new ListViewItem();
            item.SubItems.Add("");
            item.Tag = stdSample;

            if (!SetItemFromStdSample(item, stdSample))
                return;

            this.listSamples.Items.Add(item);
        }

        // Set a StdSample to a ListSamples item
        bool SetItemFromStdSample(ListViewItem item, IStdCurve stdSample)
        {
            if (item == null || stdSample == null)
                return false;

            item.SubItems[0].Text = stdSample.Name.ToString();
            item.SubItems[1].Text = stdSample.Description;

            if (IsStandard(stdSample))
            {
                item.BackColor = Color.Red;
            }

            return true;
        }

        void AddSample()
        {
            FormAddEditSample formSample = new FormAddEditSample(null);
            if (formSample.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                IStdCurve stdSample = PCRRoot.Instance.CreateObject(ObjectType.StdCurve) as IStdCurve;
                stdSample.Name = formSample._stdCurve.Name;
                stdSample.Description = formSample._stdCurve.Description;

                AddNewItemFromStdSample(stdSample);
                PCRRoot.Instance.StdCurveManager.Add(stdSample);
            }
        }

        void EditSelectedSamples()
        {
            if (this.listSamples.SelectedIndices.Count == 0)
            {
                //MessageBox.Show("请选择一个样本", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            int selIndex = this.listSamples.SelectedIndices[0];
            ListViewItem item = this.listSamples.Items[selIndex];

            IStdCurve stdSamples = item.Tag as IStdCurve;
            if (stdSamples == null)
                return;

            FormAddEditSample formSample = new FormAddEditSample(stdSamples);
            if (formSample.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                stdSamples.Name = formSample._stdCurve.Name;
                stdSamples.Description = formSample._stdCurve.Description;
                SetItemFromStdSample(item, stdSamples);
                PCRRoot.Instance.StdCurveManager.Modify(stdSamples);
            }
        }

        void DeleteSelectedSamples()
        {
            if (this.listSamples.SelectedIndices.Count == 0)
            {
                //MessageBox.Show("请选择一个样本", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (MessageBox.Show(string.Format("确定删除选择的所有样本么？"), "提示",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                int i = this.listSamples.SelectedItems.Count;
                for (int j = 0; j < i; j++)
                {
                    IStdCurve stdSamples = this.listSamples.Items[this.listSamples.SelectedIndices[0]].Tag as IStdCurve;
                    PCRRoot.Instance.StdCurveManager.Remove(stdSamples);
                    this.listSamples.Items.RemoveAt(this.listSamples.SelectedIndices[0]);
                }

                if (this.listSamples.Items.Count > 0)
                {
                    this.listSamples.Items[0].Selected = true;
                }
                else
                {
                    this.listSampleData.Items.Clear();
                    UpdateCharts();
                }
            }
        }

        void UpdateStdSamples(IStdCurve stdSamples)
        {
            if (stdSamples == null)
                return;

            // Update the list
            this.listSampleData.Items.Clear();
            foreach (IStdSampleData sampleData in stdSamples.SampleDataList)
            {
                AddNewItemToSampleDataList(sampleData);
            }

            // Update the charts
            UpdateCharts();
        }

        #endregion

        #region "Current Sample Data Event"

        private void btnAddSampleData_Click(object sender, EventArgs e)
        {
            this.listSampleData.ItemChecked -= new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);
            
            AddSampleData();

            this.listSampleData.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);
        }

        private void btnModidySampleData_Click(object sender, EventArgs e)
        {
            this.listSampleData.ItemChecked -= new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);

            EditSelectedSampleData();

            this.listSampleData.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);
        }

        private void listSampleData_DoubleClick(object sender, EventArgs e)
        {
            this.listSampleData.ItemChecked -= new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);

            EditSelectedSampleData();

            this.listSampleData.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);
        }

        private void btnDeleteSampleData_Click(object sender, EventArgs e)
        {
            DeleteSelectedSampleData();
        }

        private void tsmAddData_Click(object sender, EventArgs e)
        {
            this.listSampleData.ItemChecked -= new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);

            AddSampleData();

            this.listSampleData.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);
        }

        private void tsmModifyData_Click(object sender, EventArgs e)
        {
            this.listSampleData.ItemChecked -= new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);

            EditSelectedSampleData();

            this.listSampleData.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listSampleData_ItemChecked);
        }

        private void tsmDeleteData_Click(object sender, EventArgs e)
        {
            DeleteSelectedSampleData();
        }

        private void tsmSelectAllData_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in this.listSampleData.Items)
            {
                item.Selected = true;
            }
        }

        private void listSampleData_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            ListViewItem item = e.Item;
            if (item == null) return;

            IStdSampleData data = item.Tag as IStdSampleData;
            data.Valid = !(data.Valid);

            if (this.listSamples.SelectedItems.Count == 0) return;
            IStdCurve stdSamples = this.listSamples.SelectedItems[0].Tag as IStdCurve;
            foreach (IStdSampleData sampledata in stdSamples.SampleDataList)
            {
                if (sampledata.ObjectID == data.ObjectID)
                {
                    sampledata.CellCount = data.CellCount;
                    sampledata.CTVal = data.CTVal;
                    sampledata.Valid = data.Valid;
                    PCRRoot.Instance.StdCurveManager.Modify(stdSamples);
                    break;
                }
            }

            UpdateCharts();
        }

        #endregion

        #region "Current Sample Date Methods"

        void AddNewItemToSampleDataList(IStdSampleData sampleData)
        {
            ListViewItem item = new ListViewItem();
            item.SubItems.Add("");
            item.SubItems.Add("");
            item.SubItems.Add("");

            if (!SetItemFromSampleData(item, sampleData))
                return;

            this.listSampleData.Items.Add(item);
        }

        bool SetItemFromSampleData(ListViewItem item, IStdSampleData sampleData)
        {
            if (item == null || sampleData == null)
                return false;

            item.Checked = sampleData.Valid;
            item.SubItems[1].Text = sampleData.CTVal.ToString();
            item.SubItems[2].Text = sampleData.CellCount.ToString();
            item.Tag = sampleData;
            
            return true;
        }

        void EditSelectedSampleData()
        {
            if (this.listSampleData.SelectedItems.Count <= 0)
                return;

            int index = this.listSampleData.SelectedIndices[0];
            ListViewItem item = this.listSampleData.Items[index];
            IStdSampleData data = item.Tag as IStdSampleData;
            FormAddEditSampleData formEdit = new FormAddEditSampleData(data);
            if (formEdit.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                IStdCurve stdSamples = this.listSamples.SelectedItems[0].Tag as IStdCurve;
                foreach(IStdSampleData sampledata in stdSamples.SampleDataList)
                {
                    if (sampledata.ObjectID == data.ObjectID)
                    {
                        sampledata.CellCount = data.CellCount;
                        sampledata.CTVal = data.CTVal;
                        sampledata.Valid = data.Valid;
                        PCRRoot.Instance.StdCurveManager.Modify(stdSamples);
                        break;
                    }
                }

                SetItemFromSampleData(item, formEdit._sampleData);
                UpdateCharts();
            }
        }

        void AddSampleData()
        {
            if (this.listSamples.SelectedIndices.Count == 0)
            {
                MessageBox.Show("请选择一个样本", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            IStdCurve stdSamples = this.listSamples.SelectedItems[0].Tag as IStdCurve;
            if (stdSamples == null)
            {
                MessageBox.Show("请先选择一个样本", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            FormAddEditSampleData formAdd = new FormAddEditSampleData(null);
            if (DialogResult.OK == formAdd.ShowDialog())
            {
                stdSamples.SampleDataList.Add(formAdd._sampleData);
                PCRRoot.Instance.StdCurveManager.Modify(stdSamples);
                AddNewItemToSampleDataList(formAdd._sampleData);
                UpdateCharts();
            }
        }

        void DeleteSelectedSampleData()
        {
            if (this.listSampleData.SelectedIndices.Count == 0)
            {
                return;
            }

            if (MessageBox.Show(string.Format("确定删除选择的所有样本数据么？"), "提示",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                int i = this.listSampleData.SelectedItems.Count;
                for (int j = 0; j < i; j++)
                {
                    IStdSampleData sampleData = this.listSampleData.SelectedItems[0].Tag as IStdSampleData;
                    IStdCurve stdSamples = this.listSamples.SelectedItems[0].Tag as IStdCurve;
                    if (stdSamples != null)
                    {
                        stdSamples.SampleDataList.Remove(sampleData);
                        PCRRoot.Instance.StdCurveManager.Modify(stdSamples);
                    }

                    this.listSampleData.Items.RemoveAt(this.listSampleData.SelectedIndices[0]);
                }

                UpdateCharts();
            }
        }
        #endregion

        #region "Chart Operation"

        void UpdateCharts()
        {
            if (this.listSamples.SelectedItems.Count == 0) return;

            IStdCurve stdSamples = this.listSamples.SelectedItems[0].Tag as IStdCurve;
            if (stdSamples == null) return;
            
            IList<IStdSampleData> samples = stdSamples.SampleDataList;
            if(samples == null) return;

            int iValidData = 0;
            foreach (IStdSampleData data in samples)
            {
                if (data.Valid) iValidData++;
            }

            ClearChartPoints();

            double maxX = 10;
            double minX = 0;
            double maxY = 5;
            double minY = 0;
            // Add revised chart
            if (iValidData >= 2)
            {
                IStdCurveParam param = stdSamples.CurveParam;
                if (param != null)
                {
                    //maxX = SampleData.CellCountLog10(samples[0].CellCount);
                    //minX = SampleData.CellCountLog10(samples[0].CellCount);                    
                    maxX = Math.Round(Math.Log10(samples[0].CellCount), PCRRoot.Instance.ConfigManager.DigitialPrecision);
                    minX = Math.Round(Math.Log10(samples[0].CellCount), PCRRoot.Instance.ConfigManager.DigitialPrecision);
                    maxY = samples[0].CTVal;
                    minY = samples[0].CTVal;

                    foreach (IStdSampleData data in samples)
                    {
                        // Filter invalid data
                        if (!data.Valid) continue;

                        // Calc each value
                        double revisedCT = PCRRoot.Instance.Calculator.GetRevisedCT(param.KVal,param.BVal,data.CellCount);

                        //maxX = Math.Max(maxX, SampleData.CellCountLog10(data.CellCount));
                        //minX = Math.Min(minX, SampleData.CellCountLog10(data.CellCount));
                        maxX = Math.Max(maxX, Math.Round(Math.Log10(data.CellCount), PCRRoot.Instance.ConfigManager.DigitialPrecision));
                        minX = Math.Min(minX, Math.Round(Math.Log10(data.CellCount), PCRRoot.Instance.ConfigManager.DigitialPrecision));
                        maxY = Math.Max(maxY, revisedCT);
                        minY = Math.Min(minY, revisedCT);

                        // Also change the value
                        //AddOnePointsToChart(SampleData.CellCountLog10(data.CellCount), data.CTVal, revisedCT);
                        AddOnePointsToChart(Math.Round(Math.Log10(data.CellCount), PCRRoot.Instance.ConfigManager.DigitialPrecision), data.CTVal, revisedCT);
                    }                    

                    lblStdCurve.Text = string.Format("Y = {0}lgX{1}{2}，对应的K值为{0}", param.KVal, (param.BVal >=0 )?"+":"" ,param.BVal);
                    lblE.Text = string.Format("{0}", param.EVal);
                    lblR2.Text = string.Format("{0}，对应的R值为{1}", param.R2Val, param.RVal);
                    lblHint.Text = string.Format("计算成功！");
                }
                else
                {
                    lblStdCurve.Text = string.Format("None");
                    lblE.Text = string.Format("None");
                    lblR2.Text = string.Format("None");
                    lblHint.Text = string.Format("数据有误，无法计算出公式，请检查数据！");

                    //AddOnePointsToChart(0, 0, 0);
                }
            }
            else
            {
                // Update the text
                lblStdCurve.Text = string.Format("None");
                lblE.Text = string.Format("None");
                lblR2.Text = string.Format("None");
                lblHint.Text = string.Format("数据不足，至少需要两份样本数据！");
                //AddOnePointsToChart(0, 0, 0);
            }

            SetChartXYField(maxX, minX, maxY, minY);
        }

        private void ReSetChartSize()
        {
            standardChart.Width = this.panel3.Width;
            standardChart.Height = this.panel3.Height;
        }

        private void ClearChartPoints()
        {
            this.standardChart.Series[0].Points.Clear();
            this.standardChart.Series[1].Points.Clear();
        }

        private void AddOnePointsToChart(double X, double Y1, double Y2)
        {    
            this.standardChart.Series[0].Points.AddXY(X, Y1);
            this.standardChart.Series[1].Points.AddXY(X, Y2);
        }

        private void SetChartXYField(double maxX, double minX, double maxY, double minY)
        {
            this.standardChart.ChartAreas[this.standardChart.Series[0].ChartArea].AxisX.Maximum = maxX + (maxX - minX) / 10;
            this.standardChart.ChartAreas[this.standardChart.Series[0].ChartArea].AxisX.Minimum = minX - (maxX - minX) / 10;
            this.standardChart.ChartAreas[this.standardChart.Series[0].ChartArea].AxisY.Maximum = maxY + (maxY - minY) / 10;
            this.standardChart.ChartAreas[this.standardChart.Series[0].ChartArea].AxisY.Minimum = minY - (maxY - minY) / 10;
        }
        #endregion

        private void listSampleData_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // 检查点击的列是不是现在的排序列
            if (e.Column == this.lvwColumnSorter.SortColumn)
            {
                // 重新设置此列的排序方法.
                if (this.lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    this.lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    this.lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // 设置排序列，默认为正向排序
                this.lvwColumnSorter.SortColumn = e.Column;
                this.lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // 用新的排序方法对ListView排序
            this.listSampleData.Sort();
        }
    }

    /// <summary>
    /// 继承自IComparer
    /// </summary>
    public class ListViewColumnSorter : IComparer
    {
        /// <summary>
        /// 指定按照哪个列排序
        /// </summary>
        private int ColumnToSort;
        /// <summary>
        /// 指定排序的方式
        /// </summary>
        private SortOrder OrderOfSort;
        /// <summary>
        /// 声明CaseInsensitiveComparer类对象，
        /// 参见ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpref/html/frlrfSystemCollectionsCaseInsensitiveComparerClassTopic.htm
        /// </summary>
        private CaseInsensitiveComparer ObjectCompare;

        /// <summary>
        /// 构造函数
        /// </summary>
        public ListViewColumnSorter()
        {
            // 默认按第一列排序
            ColumnToSort = 0;

            // 排序方式为不排序
            OrderOfSort = SortOrder.None;

            // 初始化CaseInsensitiveComparer类对象
            ObjectCompare = new CaseInsensitiveComparer();
        }

        /// <summary>
        /// 重写IComparer接口.
        /// </summary>
        /// <param name="x">要比较的第一个对象</param>
        /// <param name="y">要比较的第二个对象</param>
        /// <returns>比较的结果.如果相等返回0，如果x大于y返回1，如果x小于y返回-1</returns>
        public int Compare(object x, object y)
        {
            int compareResult;
            ListViewItem listviewX, listviewY;

            // 将比较对象转换为ListViewItem对象
            listviewX = (ListViewItem)x;
            listviewY = (ListViewItem)y;

            // 比较
            compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);

            // 根据上面的比较结果返回正确的比较结果
            if (OrderOfSort == SortOrder.Ascending)
            {
                // 因为是正序排序，所以直接返回结果
                return compareResult;
            }
            else if (OrderOfSort == SortOrder.Descending)
            {
                // 如果是反序排序，所以要取负值再返回
                return (-compareResult);
            }
            else
            {
                // 如果相等返回0
                return 0;
            }
        }

        /// <summary>
        /// 获取或设置按照哪一列排序.
        /// </summary>
        public int SortColumn
        {
            set
            {
                ColumnToSort = value;
            }
            get
            {
                return ColumnToSort;
            }
        }

        /// <summary>
        /// 获取或设置排序方式.
        /// </summary>
        public SortOrder Order
        {
            set
            {
                OrderOfSort = value;
            }
            get
            {
                return OrderOfSort;
            }
        }

    }
}
